﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WPFByCoreApp
{
    /// <summary>
    /// Interaction logic for TestDrawGlyphRunWindow.xaml
    /// </summary>
    public partial class TestDrawGlyphRunWindow : Window
    {

        public TestDrawGlyphRunWindow()
        {
            InitializeComponent();

            this.grid1.Children.Add(new MyElement(this));

 
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            //var drawingVisual = new DrawingVisual();
            //using (var drawingContext = drawingVisual.RenderOpen())
            //{
            //    var fontFamily = new FontFamily("微软雅黑");
            //    Typeface typeface = fontFamily.GetTypefaces().First();
            //    //bool success = typeface.TryGetGlyphTypeface(out GlyphTypeface glyphTypeface);

            //    var text = "林德熙abc123ATdVACC";

            //    //List<ushort> glyphIndices = new List<ushort>();
            //    //List<double> advanceWidths = new List<double>();
            //    //List<Point> glyphOffsets = new List<Point>();
            //    //var fontSize = 30;

            //    //for (var i = 0; i < text.Length; i++)
            //    //{
            //    //    var c = text[i];
            //    //    var glyphIndex = glyphTypeface.CharacterToGlyphMap[c];
            //    //    glyphIndices.Add(glyphIndex);


            //    //    var width = glyphTypeface.AdvanceWidths[glyphIndex] * fontSize;
            //    //    advanceWidths.Add(width);

            //    //    glyphOffsets.Add(new Point(fontSize * i, 0));

            //    //}

            //    var location = new Point(10, 100);

            //    //XmlLanguage defaultXmlLanguage = XmlLanguage.GetLanguage(CultureInfo.CurrentUICulture.IetfLanguageTag);
            //    var pixelsPerDip = (float)VisualTreeHelper.GetDpi(Application.Current.MainWindow).PixelsPerDip;


            //    //var glyphRun = new GlyphRun
            //    //(
            //    //    glyphTypeface,
            //    //    bidiLevel: 0,
            //    //    isSideways: false,
            //    //    renderingEmSize: fontSize,
            //    //    pixelsPerDip: pixelsPerDip,   // 只有在高版本的 .NET 才有此参数
            //    //    glyphIndices: glyphIndices,
            //    //    baselineOrigin: location,     // 设置文本的偏移量
            //    //    advanceWidths: advanceWidths, // 设置每个字符的字宽，也就是字号
            //    //    glyphOffsets: null,           // 设置每个字符的偏移量，可以为空
            //    //    characters: text.ToCharArray(),
            //    //    deviceFontName: null,
            //    //    clusterMap: null,
            //    //    caretStops: null,
            //    //    language: defaultXmlLanguage
            //    //);

            //    //drawingContext.DrawGlyphRun(Brushes.White, glyphRun);

            //    FormattedText formattedText = new FormattedText(text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, typeface, 30, Brushes.Red, pixelsPerDip);

            //    drawingContext.DrawText(formattedText, location);
            //}
            //Background = new VisualBrush(drawingVisual);
        }
    }

    public class MyElement : UIElement
    {
        private MyBorder[] myBorders;

        private Brush brush;

        private Pen pen;


        private Pen pen1;

        private object IsLock = new object();

        private Window window;

        private double Left, Top, ActualWidth, ActualHeight;

        public MyElement(Window w)
        {
            window = w;

            myBorders = new MyBorder[200];
            brush = new SolidColorBrush(Colors.Red);
            pen = new Pen(new SolidColorBrush(Colors.Gray), 3);
            pen1 = new Pen(new SolidColorBrush(Colors.Red), 3);

            Rect rect = new Rect();

            w.LocationChanged += W_LocationChanged;
            w.SizeChanged += W_SizeChanged;

            Task.Run(delegate
            {
                while (true)
                {
                    rect.X = Left;
                    rect.Y = Top;
                    rect.Width = ActualWidth;
                    rect.Height = ActualHeight;
              
                    Cal(rect);

                    this.Dispatcher.Invoke(delegate
                    {
                        this.InvalidateVisual();
                    }, System.Windows.Threading.DispatcherPriority.SystemIdle
                    );


                    Thread.Sleep(40);
                }

            });
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);

            lock (IsLock)
            {

                PathGeometry pathGeometry = new PathGeometry();

                foreach (var border in myBorders)
                {
                    if (border != null)
                    {
                        drawingContext.DrawRectangle(Brushes.White, border.IsSelected ? pen1 : pen, border.rect);

                        PathFigure pathFigure = new PathFigure();

                        for (int i = 0; i < border.traces.Count(); i++)
                        {
                            if (i == 0)
                            {
                                pathFigure.StartPoint = border.traces[i];
                                pathFigure.IsClosed = false;
                            }
                            else
                            {
                                pathFigure.Segments.Add(new LineSegment(border.traces[i], false));
                            }
                        }

                        pathGeometry.Figures.Add(pathFigure);


                        //Create a StreamGeometry to use to specify myPath.
                        //StreamGeometry theGeometry = new StreamGeometry();

                        //using (StreamGeometryContext ctx = theGeometry.Open())
                        //{
                        //    for (int i = 0; i < border.traces.Count(); i++)
                        //    {
                        //        if (i == 0)
                        //        {
                        //            ctx.BeginFigure(border.traces[i], true /* is filled */, true /* is closed */);
                        //        }
                        //        else
                        //        {
                        //            ctx.LineTo(border.traces[i], true /* is stroked */, false /* is smooth join */);
                        //        }
                        //    }

                        //}


                        //theGeometry.FillRule = FillRule.EvenOdd;

                        //theGeometry.Freeze();

                        //drawingContext.DrawGeometry(Brushes.Black, null, theGeometry);

                    }
                }


                drawingContext.DrawGeometry(Brushes.Black, null, pathGeometry);

                Debug.WriteLine("OnRender---date:" + DateTime.Now.ToString("mm:ss.fff"));
            }

        }

        private void Cal(Rect rect)
        {
            lock (IsLock)
            {
                int MaxBorder = 200;
                int ColNum = 4;
                int RowNum = MaxBorder / ColNum;

                double BorderWidth = rect.Width / ColNum;
                double BorderHeight = rect.Height / RowNum;

                int ColIndex = 0;
                int RowIndex = 0;

                for (int i = 0; i < MaxBorder; i++)
                {
                    if (myBorders[i] == null)
                        myBorders[i] = new MyBorder();

                    myBorders[i].rect.X = BorderWidth * ColIndex;
                    myBorders[i].rect.Y = BorderHeight * RowIndex;
                    myBorders[i].rect.Width = BorderWidth;
                    myBorders[i].rect.Height = BorderHeight;

                    myBorders[i].Init();

                    ColIndex++;

                    if (ColIndex > (ColNum - 1))
                    {
                        ColIndex = 0;
                        RowIndex++;
                    }
                }
            }

        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point p = e.GetPosition(this);
                foreach (var border in myBorders)
                {
                    if (border.IsIn(p))
                        border.IsSelected = true;
                    else
                        border.IsSelected = false;
                }

            }

            base.OnMouseDown(e);
        }


        private void W_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            Left = window.Left;
            Top = window.Top;
            ActualWidth = window.ActualWidth;
            ActualHeight = window.ActualHeight;
        }

        private void W_LocationChanged(object sender, EventArgs e)
        {
            Left = window.Left;
            Top = window.Top;
            ActualWidth = window.ActualWidth;
            ActualHeight = window.ActualHeight;
        }



    }


    public class MyBorder
    {
        public Rect rect;

        public Point[] traces;

        public bool IsSelected;

        static Random random = new Random();

        public MyBorder()
        {
            rect = new Rect();
            traces = new Point[100];

        }

        public void Init()
        {
            for (int i = 0; i < traces.Length; i++)
            {
                traces[i].X = random.Next((int)rect.Left, (int)(rect.Left + rect.Width));
                traces[i].Y = random.Next((int)rect.Top, (int)(rect.Top + rect.Height));
            }

        }


        public bool IsIn(Point p)
        {
            return rect.Contains(p.X, p.Y);
        }
    }




    //    class Foo11 : UIElement
    //    {
    //        public string Text { set; get; } = string.Empty;

    //        protected override void OnRender(DrawingContext drawingContext)
    //        {
    //            var fontFamily = new FontFamily("微软雅黑");

    //            var fontSize = 15;
    //            var y = 0;
    //            drawingContext.PushOpacity(0.3);
    //            foreach (var typeface in fontFamily.GetTypefaces().Skip(1).Take(1))
    //            {
    //                double offset = 3;

    //                var baseLine = fontFamily.GetBaseline(fontSize);

    //                if (typeface.TryGetGlyphTypeface(out var glyphTypeface))
    //                {
    //                    foreach (var c in Text)
    //                    {
    //                        if (glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out var glyphIndex))
    //                        {
    //                            // 在排版，不适合将每个字符的宽度独立进行计算。有很多字符是需要重叠布局的
    //                            var width = glyphTypeface.AdvanceWidths[glyphIndex] * fontSize;
    //                            width = GlyphExtension.RefineValue(width);

    //#pragma warning disable 618 // 忽略调用废弃构造函数
    //                            var glyphRun = new GlyphRun(
    //#pragma warning restore 618
    //                                glyphTypeface,
    //                                0,
    //                                false,
    //                                fontSize,
    //                                new[] { glyphIndex },
    //                                new Point(offset, baseLine + y),
    //                                new[] { width },
    //                                DefaultGlyphOffsetArray,
    //                                new char[] { c },
    //                                null,
    //                                null,
    //                                null, DefaultXmlLanguage);

    //                            drawingContext.DrawLine(new Pen(Brushes.Black, 2), new Point(offset, y), new Point(offset + width, y));

    //                            drawingContext.DrawGlyphRun(Brushes.Coral, glyphRun);

    //                            var glyphSize = glyphRun.GetSize(fontFamily.LineSpacing);

    //                            drawingContext.DrawRectangle(null, new Pen(Brushes.Black, 2), new Rect(new Point(offset, y), glyphSize));

    //                            // 布局的字符宽度
    //                            offset += width;
    //                        }
    //                    }
    //                }

    //                y += fontSize;
    //            }
    //            drawingContext.Pop();
    //        }

    //        private static readonly Point[] DefaultGlyphOffsetArray = new Point[] { new Point() };

    //        private static readonly XmlLanguage DefaultXmlLanguage =
    //            XmlLanguage.GetLanguage(CultureInfo.CurrentUICulture.IetfLanguageTag);
    //    }
}
